-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RelayMiner] Implement relayminer query caching #1050
base: main
Are you sure you want to change the base?
Conversation
The image is going to be pushed after the next commit. You can use If you also want to run E2E tests, please add |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@red-0ne I did a first partial review but have a lot of comments & questions.
Here's a high-level summary but PTAL at the actual comments as well:
- Need to understand if/how this can build on top of [Off-chain] feat: in-memory query cache(s) #994 w/ @bryanchriswhite
- See a few comments (logs + comments) that need to be addressed in multiple places
- I’m a bit concerned (and don’t understand) how we’re not using “height” to retrieve things from the cache, especially when values are always changing
- When does the cache ever get cleared?
- Light on tests
- I’d be interested to see numbers of performance improvement
@@ -49,11 +53,19 @@ func NewSharedQuerier(deps depinject.Config) (client.SharedQueryClient, error) { | |||
// Once `ModuleParamsClient` is implemented, use its replay observable's `#Last()` method | |||
// to get the most recently (asynchronously) observed (and cached) value. | |||
func (sq *sharedQuerier) GetParams(ctx context.Context) (*sharedtypes.Params, error) { | |||
// Get the params from the cache if they exist. | |||
if params, found := sq.paramsCache.Get(); found { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned (and don't fully understand) the lack of a "height" param when retrieving things from the cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cache implementation does not add any new functionality besides caching whatever has been queried.
It does not alter the RelayMiner
s current behavior
RelayMiner
cold start- React to
Param
s change
For those reasons, it does not leverage historical data that justifies the usage of height
for cache querying.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that the cache implementations here are NOT historical; i.e. ONLY the most recently observed value is cached for each ParamsCache
instance (or key, in the case of KeyValueCache
).
While #994 does include historical caching as well (via the HistoricalQueryCache
interface, that's an additional and distinct feature.
This shouldn't be necessary here because we're clearing the cache on every new block. The end result being, somewhat sub-optimal, but significant caching. This reformulates the number off-chain queries from being a function of API usage, to no more than one per block, per cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice one @red-0ne! 🙌
Thanks for doing this! ❤️
|
||
// WithNewBlockCacheClearing is a cache option that clears the cache every time | ||
// a new block is observed. | ||
func WithNewBlockCacheClearing[C Cache](ctx context.Context, deps depinject.Config, cache C) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥 🔥 🔥
} | ||
|
||
// KeyValueCache is an interface for a simple in-memory key-value cache implementation. | ||
type KeyValueCache[V any] interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pkg/client/query/sessionquerier.go
Outdated
clientConn grpc.ClientConn | ||
sessionQuerier sessiontypes.QueryClient | ||
sharedQueryClient client.SharedQueryClient | ||
sessionsCache KeyValueCache[*sessiontypes.Session] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@@ -49,11 +53,19 @@ func NewSharedQuerier(deps depinject.Config) (client.SharedQueryClient, error) { | |||
// Once `ModuleParamsClient` is implemented, use its replay observable's `#Last()` method | |||
// to get the most recently (asynchronously) observed (and cached) value. | |||
func (sq *sharedQuerier) GetParams(ctx context.Context) (*sharedtypes.Params, error) { | |||
// Get the params from the cache if they exist. | |||
if params, found := sq.paramsCache.Get(); found { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that the cache implementations here are NOT historical; i.e. ONLY the most recently observed value is cached for each ParamsCache
instance (or key, in the case of KeyValueCache
).
While #994 does include historical caching as well (via the HistoricalQueryCache
interface, that's an additional and distinct feature.
This shouldn't be necessary here because we're clearing the cache on every new block. The end result being, somewhat sub-optimal, but significant caching. This reformulates the number off-chain queries from being a function of API usage, to no more than one per block, per cache.
Summary
Implements caching layer for query clients to reduce network calls and improve performance
Primary Changes:
KeyValueCache
andParamsCache
interfaces with thread-safe implementationsAccount
,Application
,Bank
,Service
, etc.)WithNewBlockCacheClearing
optionSecondary Changes:
sync.Mutex
implementation inaccQuerier
with new cache interfaceIssue
The RelayMiner RPC queries are not cached, which puts excessive load on the configured full node, degrading the performance of both off-chain and on-chain components.
Type of change
Select one or more from the following:
consensus-breaking
label if so. See [Infra] Automatically add theconsensus-breaking
label #791 for detailsSanity Checklist
assignees
,reviewers
,labels
,project
,iteration
andmilestone
make docusaurus_start
make go_develop_and_test
andmake test_e2e
devnet-test-e2e
label to run E2E tests in CI